﻿
namespace n_HardModule
{
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

using n_GUIcoder;
using n_MyFileObject;
using n_UserModule;
using n_UIModule;
using n_GUIset;
using n_MyFileObjectPanel;
using n_Shape;
using n_MyObjectList;
using n_MyObject;
using n_MainSystemData;
using n_MidPortList;
using n_SimulateObj;

//*****************************************************
//硬件组件类
public class HardModule: MyFileObject
{
	public delegate void D_ScaleChanged();
	public static D_ScaleChanged ScaleChanged;
	
	public float tmyX;
	public float tmyY;
	
	//端口列表不包含空项
	public Port[] PORTList;
	public Port[] ZWireList;
	
	public int SourceWidth;
	public int SourceHeight;
	public Image SourceImage;
	
	public string UserName;
	//public string DeviceType;
	public string ImageList;
	public string DriverFilePath;
	
	string Config;
	public string[] ConfigList;
	
	Pen InterfacePreLinkPen;
	Pen InterfaceLinkPen;
	
	SolidBrush SelectModulebackBrush;
	SolidBrush MouseOnModulebackBrush;
	
	public bool isClientModule;
	public bool isClientControlPad;
	public bool isVHRemoModule;
	public bool isYuanJian;
	
	public string PackOwner;
	public bool PackOpenMPort;
	public bool PackHid;
	
	public bool isCircuit;
	public bool isAnalog;
	public bool isDigital;
	public bool isBitmap;
	
	public bool IO_Base;
	
	//这个不要改, 因为组件库初始化需要用到这个倍数
	public static float Scale = 0.5f;
	
	public SimulateObj[] SimList;
	string InitDataList;
	
	public float CScale;
	
	int Lastmidx;
	int Lastmidy;
	
	int Start_mX;
	int Start_mY;
	
	public bool SwapPort;
	
	public Elm.E_CC_Type CC_Type;
	public int CC_ID;
	
	public bool isCC_Error;
	
	//设置仿真时候是否显示大图 (目前仅用于ST7789)
	public static bool ShowBigImage;
	
	//--------------------------------------------
	
	static Pen 组件高亮边框_Pen2;
	
	
	//初始化
	public static void Init()
	{
		Elm.Init();
		
		组件高亮边框_Pen2 = new Pen( Color.OrangeRed, 3 );
		
		SimulateObj.Init();
	}
	
	//构造函数,根据文件名加载组件,文件名为全路径
	public HardModule( string ModuleFilePath ): base()
	{
		ScaleChanged += MyScaleChanged;
		CScale = Scale;
		
		temp_ModuleFilePath = ModuleFilePath;
		
		int tLength = 0;
		int tZLength = 0;
		BasePort[] tPortList = null;
		BasePort[] tZWireList = null;
		Size sz = Size.Empty;
		SourceImage = null;
		string SimValueList = null;
		
		PackHid = false;
		
		//仅用于模块更新时的提示属性
		string ImagePath = null;
		
		UserName = null;
		//ChipType = null;
		ImageList = null;
		DriverFilePath = null;
		Config = null;
		MesFilePath = null;
		EXMes = null;
		
		isCircuit = false;
		isAnalog = false;
		isDigital = false;
		isBitmap = false;
		IO_Base = false;
		SwapPort = false;
		
		s_t_Angle = false;
		
		PackOwner = null;
		PackOpenMPort = false;
		
		InitDataList = null;
		GUIcoder.LoadModule(
			ModuleFilePath,
			ref tPortList,
			ref tZWireList,
			ref tLength,
			ref tZLength,
			ref ImageName,
			ref ImagePath,
			ref SourceImage,
			ref UserName,
			ref ChipType,
			ref ImageList,
			ref DriverFilePath,
			ref Config,
			ref MesFilePath,
			ref EXMes,
			ref sz,
			ref InitDataList,
			ref SimValueList,
			ref isControlModule,
			ref isClientModule,
			ref isClientControlPad,
		    ref isClientChannel,
			ref isVHRemoModule,
			ref isYuanJian,
			ref CanSwap,
			ref Version );
		
		//电路类模块处理
		if( EXMes != null && EXMes.Length >= 1 ) {
			if( EXMes[0] == '0' ) {
				isAnalog = true;
			}
			if( EXMes[0] == '1' ) {
				isDigital = true;
			}
			if( EXMes[0] == '2' ) {
				isBitmap = true;
				isAnalog = true;
			}
			isCircuit = isAnalog || isDigital;
		}
		if( isCircuit ) {
			isYuanJian = true;
			CanFloat = true;
			CanSwap = true;
			if( isCircuit ) {
				CScale = 1.0f;
			}
			
			//因为端口一半在模块外, 所以需要加pad (端口半径)
			ExXPadding = 6;
			ExYLPadding = 6;
			ExYHPadding = 6;
			
			CC_Type = Elm.GetCC_Type( ImageName );
		}
		//驱动库进行配置
		if( Config != null && Config != "" ) {
			ConfigList = Config.Split( '`' );
		}
		
		if( sz != Size.Empty ) {
			SourceWidth = sz.Width;
			SourceHeight = sz.Height;
		}
		else {
			SourceWidth = SourceImage.Width;
			SourceHeight = SourceImage.Height;
		}
		
		Width = (int)(SourceWidth * CScale);
		Height = (int)(SourceHeight * CScale);
		
		SimList = new SimulateObj[32];
		if( SimValueList != null ) {
			string[] ss  = SimValueList.Split( '\n' );
			for( int i = 0; i < ss.Length; ++i ) {
				SimList[i] = new SimulateObj( this, i );
				SimList[i].SetValue( ss[i] );
			}
		}
		
		tmyX = (float)Width/2 - Width/2;
		tmyY = (float)Height/2 - Height/2;
		
		//端口列表规范化
		PORTList = new Port[ tLength ];
		for( int i = 0; i < tLength; ++i ) {
			float px = tPortList[ i ].X;
			float py = tPortList[ i ].Y;
			if( isCircuit ) {
				px = n_Common.Common.GetCrossValue( px + MidX ) - MidX;
				py = n_Common.Common.GetCrossValue( py + MidY ) - MidY;
			}
			PORTList[ i ] = new Port( this, i,
			                         tPortList[ i ].Name, tPortList[ i ].FuncType, tPortList[ i ].FuncName, tPortList[ i ].Style, null,
			                         tPortList[ i ].DirType, px, py, false, tPortList[ i ].ExtValue );
		}
		
		//总线列表规范化
		ZWireList = new Port[ tZLength ];
		for( int i = 0; i < tZLength; ++i ) {
			ZWireList[ i ] = new Port( this, i,
			                          tZWireList[ i ].Name, tZWireList[ i ].FuncType, tZWireList[ i ].FuncName, tZWireList[ i ].Style, tZWireList[ i ].SubPortConfig,
			                         tZWireList[ i ].DirType, tZWireList[ i ].X, tZWireList[ i ].Y, true, tZWireList[ i ].ExtValue );
		}
		//整理同名端口
		DealSamePort();
		
		//重新设置端口列表的位置
		ResetPortList();
		
		if( SystemData.isBlack ) {
			InterfacePreLinkPen = new Pen( Color.LightGreen, 3 );
			InterfacePreLinkPen.DashStyle = DashStyle.Dot;
			
			InterfaceLinkPen = new Pen( Color.Orange, 3 );
			//InterfaceLinkPen.EndCap = LineCap.ArrowAnchor;
			//System.Drawing.Drawing2D.AdjustableArrowCap AC = new AdjustableArrowCap( 5, 4, true );
			//InterfaceLinkPen.CustomEndCap = AC;
		}
		else {
			InterfacePreLinkPen = new Pen( Color.ForestGreen, 3 );
			InterfacePreLinkPen.DashStyle = DashStyle.Dot;
			
			InterfaceLinkPen = new Pen( Color.OrangeRed, 3 );
			//InterfaceLinkPen.EndCap = LineCap.ArrowAnchor;
			//System.Drawing.Drawing2D.AdjustableArrowCap AC = new AdjustableArrowCap( 5, 4, true );
			//InterfaceLinkPen.CustomEndCap = AC;
		}
		
		MouseOnModulebackBrush = new SolidBrush( Color.FromArgb( 90, Color.White ) );
		SelectModulebackBrush = new SolidBrush( Color.FromArgb( 80, Color.Red ) );
		
		if( ImageName == SPMoudleName.mbb || ImageName == SPMoudleName.SYS_iport || ImageName == SPMoudleName.SYS_NOHIT ) {
			this.CanFloat = true;
		}
	}
	
	//--------------------------------------------
	
	//放缩比例改变事件
	public void MyScaleChanged()
	{
		CScale = Scale;
		
		Lastmidx = MidX;
		Lastmidy = MidY;
		
		ResetInterfaceLocation();
		
		Width = (int)(SourceWidth * Scale);
		Height = (int)(SourceHeight * Scale);
		
		ResetPortList();
		
		SetAngle( Angle );
	}
	
	//重新设置端口列表的位置
	void ResetPortList()
	{
		for( int i = 0; i < PORTList.Length; ++i ) {
			PORTList[ i ].ResetLocation();
		}
		for( int i = 0; i < ZWireList.Length; ++i ) {
			ZWireList[ i ].ResetLocation();
		}
	}
	
	//整理同名端口 - 每个端口只有一个同名端口引用, 但通过本函数特定算法可以实现支持多于2个同名端口
	//形成单链式引用
	string temp_ModuleFilePath;
	void DealSamePort()
	{
		if( ImageName == SPMoudleName.SYS_iport ) {
			return;
		}
		for( int i = 0; i < PORTList.Length; ++i ) {
			for( int j = i + 1; j < PORTList.Length; ++j ) {
				if( PORTList[i].Name == PORTList[j].Name ) {
					
					if( PORTList[i].FuncName != PortFuncName.VCC6t9V &&
						PORTList[i].FuncName != PortFuncName.VCC3_3V &&
						PORTList[i].FuncName != PortFuncName.VCC &&
						PORTList[i].FuncName != PortFuncName.UNUSED &&
						PORTList[i].FuncName != PortFuncName.AREF &&
						PORTList[i].FuncName != PortFuncName.GND &&
						PORTList[i].FuncName != PortFuncName.RESET ) {
						
						PORTList[i].SamePort = PORTList[j];
						if( !PORTList[i].isNumIdxPort() || !PORTList[j].isNumIdxPort() ) {
							n_Debug.Warning.BUG( "发现同名针脚且未设置为数字模式, 建议反馈给linkboy官方改正: " +
							                              i + "," + j + ": " + Name + "." + PORTList[i].Name + "(" + PORTList[i].ExtValue + ") " + temp_ModuleFilePath );
						}
						break;
					}
				}
			}
		}
	}
	
	//仿真启动时初始化数据表事件
	public void ResetSim()
	{
		isCC_Error = false;
		
		for( int i = 0; i < DataList.Length; ++i ) {
			DataList[i] = 0;
		}
		if( InitDataList != null ) {
		
			string dlist = InitDataList.Remove( 0, 1 );
			string[] s  =dlist.Split( ',' );
			for( int i = 0; i < s.Length; ++i ) {
				if( s[i].StartsWith( "0x" ) ) {
					DataList[i] = int.Parse( s[i].Remove( 0, 2 ), System.Globalization.NumberStyles.HexNumber );
				}
				else {
					DataList[i] = int.Parse( s[i] );
				}
			}
		}
		for( int i = 0; i < SimList.Length; ++i ) {
			if( SimList[i] != null ) {
				SimList[i].Reset();
			}
		}
	}
	
	//结束仿真
	public void StopSim()
	{
		for( int i = 0; i < SimList.Length; ++i ) {
			if( SimList[i] != null ) {
				SimList[i].Close();
			}
		}
	}
	
	//左右翻转
	public void Swap()
	{
		SwapPort = !SwapPort;
		for( int i = 0; i < PORTList.Length; ++i ) {
			switch( Angle ) {
				case 0:
				case 180:
				PORTList[ i ].X = -PORTList[ i ].X;
				switch( PORTList[ i ].DirType ) {
					case E_DirType.RIGHT: PORTList[ i ].DirType = E_DirType.LEFT; break;
					case E_DirType.LEFT: PORTList[ i ].DirType = E_DirType.RIGHT; break;
					default:	break;
				}
				break;
				case 90:
				case 270:
				PORTList[ i ].Y = -PORTList[ i ].Y;
				switch( PORTList[ i ].DirType ) {
					case E_DirType.UP: PORTList[ i ].DirType = E_DirType.DOWN; break;
					case E_DirType.DOWN: PORTList[ i ].DirType = E_DirType.UP; break;
					default:	break;
				}
				break;
			}
		}
	}
	
	//组件删除
	public override void Remove()
	{
		if( PackOwner != null ) {
			
			G.CGPanel.UnPack();
			
			//MessageBox.Show( "积木组合类扩展板目前暂时不支持删除操作" );
			//return;
		}
		
		G.SimBox.SPanel.Remove( this );
		
		//查找所有相关链接
		for( int n = 0; n < PORTList.Length; ++n ) {
			
			if( PORTList[ n ].MidPortIndex != -1 ) {
				G.CGPanel.myMidPortList.Delete( PORTList[ n ].MidPortIndex );
				PORTList[ n ].MidPortIndex = -1;
			}
		}
		//查找所有相关链接
		for( int n = 0; n < ZWireList.Length; ++n ) {
			
			if( ZWireList[ n ].MidPortIndex != -1 ) {
				G.CGPanel.myMidPortList.Delete( ZWireList[ n ].MidPortIndex );
				ZWireList[ n ].MidPortIndex = -1;
			}
		}
		
		
		//遍历组件列表,查找所有指向目标组件的链接,如果存在则提示是否删除
		foreach( MyObject mo in myObjectList ) {
		
			if( !(mo is HardModule) ) {
				continue;
			}
			HardModule cM = (HardModule)mo;
			
			//查找所有相关链接
			for( int n = 0; n < cM.PORTList.Length; ++n ) {
				if( cM.PORTList[ n ].TargetPort != null && cM.PORTList[ n ].TargetPort.Owner == this ||
				    cM.PORTList[ n ].TargetModule == this ) {
					cM.PORTList[ n ].TargetPort = null;
					cM.PORTList[ n ].TargetModule = null;
					
					if( cM.PORTList[ n ].MidPortIndex != -1 ) {
						G.CGPanel.myMidPortList.Delete( cM.PORTList[ n ].MidPortIndex );
						cM.PORTList[ n ].MidPortIndex = -1;
					}
				}
			}
			//查找所有相关链接
			for( int n = 0; n < cM.ZWireList.Length; ++n ) {
				if( cM.ZWireList[ n ].TargetPort != null && cM.ZWireList[ n ].TargetPort.Owner == this ||
				    cM.ZWireList[ n ].TargetModule == this ) {
					cM.ZWireList[ n ].TargetPort = null;
					cM.ZWireList[ n ].TargetModule = null;
					
					if( cM.ZWireList[ n ].MidPortIndex != -1 ) {
						G.CGPanel.myMidPortList.Delete( cM.ZWireList[ n ].MidPortIndex );
						cM.ZWireList[ n ].MidPortIndex = -1;
					}
				}
			}
		}
//		//查找所有相关链接
//		for( int n = 0; n < this.PORTList.Length; ++n ) {
//			if( this.PORTList[ n ].TargetPort != null ) {
//				this.PORTList[ n ].TargetPort = null;
//				this.PORTList[ n ].TargetModule = null;
//			}
//		}
		CommonRemove();
	}
	
	//组件扩展函数
	public override bool MouseIsInEX( int mX, int mY )
	{
		return false;
	}
	
	//接口自动预连接处理
	public void AutoConnectInterface()
	{
		//遍历接口列表
		for( int i = 0; n_ImagePanel.ImagePanel.Flash && i < this.LinkInterfaceList.Length; ++i ) {
			
			if( this.LinkInterfaceList[ i ][ 0 ] != "" ) {
				
				if( IPortList[ InterfaceList.Length + i ].TargetIPort == null ) {
					this.LinkInterfaceList[ i ][ 0 ] = "";
				}
				else {
					continue;
				}
			}
			
			string LinkName = this.LinkInterfaceList[ i ][ 1 ].Split( '_' )[ 1 ];
			
			int PickNumber = 0;
			string Target = null;
			int tn = 0;
			MyFileObject ta = null;
			
			if( !this.myObjectList.isModuleLib ) {
				foreach( MyObject mo in myObjectList ) {
					if( !(mo is MyFileObject) ) {
						continue;
					}
					if( mo == this ) {
						continue;
					}
					MyFileObject mm = (MyFileObject)mo;
					
					//搜索组件提供的接口列表
					for( int j = 0; j < mm.InterfaceList.Length; ++j ) {
						if( LinkName == mm.InterfaceList[ j ][ 1 ].Split( '_' )[ 1 ] ) {
							
							PickNumber++;
							Target = mm.Name + "." + mm.InterfaceList[ j ][ 2 ];
							ta = mm;
							tn = j;
						}
					}
				}
			}
			if( PickNumber == 1 ) {
				LinkInterfaceList[i ][ 0 ] = Target;
				IPortList[ InterfaceList.Length + i ].TargetIPort = ta.IPortList[tn];
			}
		}
	}
	
	//=======================================================================================================
	
	//组件绘制工作1
	//绘制组件的外形等,基础绘制工作
	public override void Draw1( Graphics g )
	{
		if( PackHid ) {
			return;
		}
		if( isNewTick != 0 ) {
			return;
		}
		Brush NameBrush;
		Brush ChipBrush;
		Brush LibNameBrush;
		if( SystemData.isBlack ) {
			NameBrush = Brushes.White;
			ChipBrush = Brushes.LightBlue;
			LibNameBrush = Brushes.White;
		}
		else {
			NameBrush = Brushes.LightSlateGray;
			ChipBrush = Brushes.CornflowerBlue;
			LibNameBrush = Brushes.Black;
		}
		if( IO_Base && !isControlModule ) {
			NameBrush = Brushes.Blue;
			ChipBrush = Brushes.CornflowerBlue;
			LibNameBrush = Brushes.Blue;
		}
		if( isUserPathMod ) {
			NameBrush = Brushes.Red;
			ChipBrush = Brushes.CornflowerBlue;
		}
		//绘制组件名称
		string chiptype = this.ChipType;
		//if( DeviceType != null && DeviceType != "" ) {
		//	chiptype = DeviceType;
		//}
		if( this.myObjectList.isModuleLib ) {
			
			SizeF s1 = g.MeasureString( chiptype, GUIset.ModuleSimNameFont );
			int ox1 = (Width-(int)s1.Width)/2;
			SizeF s2 = g.MeasureString( Name, GUIset.ModuleNameFont );
			int ox2 = (Width-(int)s2.Width)/2;
			
			if( this.SimulateType == n_GUIcoder.SimulateType.IgnoreLib ) {
				g.DrawString( "暂不支持仿真", GUIset.ModuleSimNameFont, Brushes.OrangeRed, SX, SY - 18 );
				if( chiptype != "" ) {
					g.DrawString( chiptype, GUIset.ModuleSimNameFont, ChipBrush, SX + ox1, SY - 36 );
					g.DrawString( Name, GUIset.ModuleNameFont, LibNameBrush, SX + ox2, SY - 54 );
				}
				else {
					g.DrawString( Name, GUIset.ModuleNameFont, LibNameBrush, SX + ox2, SY - 36 );
				}
			}
			else {
				if( chiptype != "" ) {
					g.DrawString( chiptype, GUIset.ModuleSimNameFont, ChipBrush, SX + ox1, SY - 18 );
					g.DrawString( Name, GUIset.ModuleNameFont, LibNameBrush, SX + ox2, SY - 36 );
				}
				else {
					g.DrawString( Name, GUIset.ModuleNameFont, LibNameBrush, SX + ox2, SY - 18 );
				}
			}
		}
		else {
			if( ImageName != SPMoudleName.SYS_iport && ImageName != SPMoudleName.SYS_PADSHAP && (isMouseOnBase || !G.CGPanel.HideName) ) {
				
				//目前小熊派的按钮不需要显示型号 避免遮挡背景
				if( chiptype != "" && chiptype != "SYS_HIDE" ) {
					g.DrawString( chiptype, GUIset.ModuleSimNameFont, ChipBrush, SX, SY - 22 );
					g.DrawString( Name, GUIset.ModuleNameFont, NameBrush, SX, SY - 40 );
				}
				else {
					if( ImageName != SPMoudleName.mbb && ImageName != SPMoudleName.SYS_NULL ) {
						g.DrawString( Name, GUIset.ModuleNameFont, NameBrush, SX, SY - 22 );
					}
				}
				DrawDebug( g, SX, SY );
			}
		}
		
		int www = Width;
		int hhh = Height;
		int ssx = SX;
		int ssy = SY;
		if( Angle == 90 || Angle == 270 ) {
			www = Height;
			hhh = Width;
			ssx = MidX - Height/2;
			ssy = MidY - Width/2;
		}
		float RolX = www/2;
		float RolY = hhh/2;
		
		//摄像机按照中心位置进行旋转
		GraphicsState gs = g.Save();
		n_SG.SG.Rotate( MidX, MidY, Angle );
		
		if( ImageName == SPMoudleName.SYS_PADSHAP ) {
			
			//绘制组件名称
			Rectangle r;
			
			if( SwapPort ) {
				//g.FillRectangle( Brushes.DarkSeaGreen, StartX + ssx + www, StartY + ssy, -www, hhh );
				r = new Rectangle( ssx + www, ssy, -www, hhh );
			}
			else {
				//g.FillRectangle( Brushes.DarkSeaGreen, StartX + ssx, StartY + ssy, www, hhh );
				r = new Rectangle( ssx, ssy, www, hhh );
			}
			GraphicsPath gp = Shape.CreateRoundedRectanglePath( r );
			g.FillPath( Brushes.Gainsboro, gp );
			g.DrawPath( Pens.SlateGray, gp );
		}
		else {
			if( isCircuit ) {
				Elm.DrawElm( this, g, ssx, ssy, www, hhh );
			}
			else {
				//判读是否为精灵
				if( InitTargetSObject is n_Sprite.Sprite ) {
					n_Sprite.Sprite sp = (n_Sprite.Sprite)InitTargetSObject;
					if( sp.ILength > 0 && sp.ImageList[0] != null ) {
						Bitmap spm = sp.ImageList[0];
						int sww = spm.Width;
						int shh = spm.Height;
						if( sww > shh ) {
							shh = shh * www / sww;
							sww = www;
						}
						else {
							sww = sww * hhh / shh;
							shh = hhh;
						}
						g.DrawImage( spm, ssx + (www-sww)/2, ssy + (hhh-shh)/2, sww, shh );
						GraphicsPath gp = n_Shape.Shape.CreateRoundedRectanglePath( new Rectangle( ssx, ssy, www, hhh ) );
						g.DrawPath( Pens.SlateGray, gp );
					}
					else {
						g.DrawImage( SourceImage, ssx, ssy, www, hhh );
					}
				}
				else {
					if( SwapPort ) {
						g.DrawImage( SourceImage, ssx + www, ssy, -www, hhh );
					}
					else {
						g.DrawImage( SourceImage, ssx, ssy, www, hhh );
					}
				}
			}
		}
		//绘制是否选中
		if( (G.CGPanel.MultEageShow && PackOwner != null) || isSelect ) {
			if( SwapPort ) {
				g.DrawRectangle( 组件高亮边框_Pen2, ssx + www, ssy, -www, hhh );
			}
			else {
				g.DrawRectangle( 组件高亮边框_Pen2, ssx, ssy, www, hhh );
			}
		}
		g.Restore( gs );
		
		//if( !GUISystemData.isBlack ) {
		//	g.DrawRectangle( Pens.Black, StartX + SX, StartY + SY, Width, Height );
		//}
		//绘制鼠标悬停时的方框
		if( ImageName != SPMoudleName.SYS_iport && ImageName != SPMoudleName.SYS_PADSHAP && !this.myObjectList.isModuleLib && !G.SimulateMode && isMouseOnBase ) {
			int x = SX - 4;
			int y = - ExYHPadding + SY - 4;
			int w = Width - 1 + 8;
			int h = Height + ExYHPadding + ExYLPadding - 1 + 8;
			
			//g.DrawRectangle( GUIset.组件高亮边框_Pen2, x, y, w, h );
			//g.DrawRectangle( GUIset.组件高亮边框_Pen1, x, y, w, h );
			
			g.DrawRectangle( GUIset.组件高亮边框_Pen1, SX, SY, Width, Height );
		}
		//绘制端口
		for( int i = 0; i < PORTList.Length; ++i ) {
			PORTList[ i ].Draw1( g );
		}
		//绘制常量信息
		if( this.myObjectList.isModuleLib ) {
			return;
		}
		//int hh = SY - 18; //模块名字过长, 会遮挡住这部分, 所以要下移一行  (这一行会导致光敏电阻参数重叠)
		int hh = SY; //模块名字过长, 会遮挡住这部分, 所以要下移一行
		
		int ListNumber = VarList.Length;
		for( int i = 0; i < ListNumber; ++i ) {
			string VarName = VarList[ i ][ GetLC() ];
			
			string Value = VarList[ i ][ 0 ];
			
			string[] VarTypeList = VarList[ i ][ 1 ].Split( '_' );
			//string VarType = VarTypeList[ 1 ];
			int xpad = 20;
			if( isCircuit ) {
				xpad = 0;
			}
			if( VarTypeList.Length >= 4 ) {
				g.DrawString( VarName + ": " + Value + " " + VarTypeList[3], GUIset.ModuleNameFont, ChipBrush, SX + Width + xpad, hh );
			}
			else {
				g.DrawString( VarName + ": " + Value, GUIset.ModuleNameFont, ChipBrush, SX + Width + xpad, hh );
			}
			hh += 20;
		}
		
		//int sy = StartY + SY + Height + 5;
		
		if( ImageName == SPMoudleName.SYS_Keyboard && ExtendValue != "" ) {
			
			//绘制加大字号
			if( KeyMes.Length == 1 ) {
				g.DrawString( KeyMes, GUIset.Font20, Brushes.DarkSlateGray, SX + 27, SY + 21 );
			}
			else {
				g.DrawString( KeyMes, GUIset.Font20, Brushes.DarkSlateGray, SX + 10, SY + 21 );
			}
			
			g.DrawString( "监控按键值: " + KeyMes, GUIset.ExpFont, Brushes.OrangeRed, SX + Width + 10, hh );
			hh += 20;
			g.DrawString( "触发间隔: " + (TickMesN / 1000f).ToString( "0.00" ) + "秒", GUIset.ExpFont, NameBrush, SX + Width + 10, hh );
		}
		else if( (ImageName == SPMoudleName.SYS_PinInput || ImageName == SPMoudleName.SYS_PinOutput) && ExtendValue != "" ) {
			g.DrawString( "引脚绑定: " + ExtendValue, GUIset.ExpFont, Brushes.OrangeRed, SX, SY + Height );
		}
		//显示存储位置
		else if( ExtendValue != "" ) {
			g.DrawString( "变量数据存放在", GUIset.ExpFont, NameBrush, SX + Width + 10, hh );
			hh += 20;
			g.DrawString( ExtendValue, GUIset.ExpFont, NameBrush, SX + Width + 10, hh );
			hh += 20;
		}
		//显示当前时间位置
		if( ExtendValue1 != "" ) {
			g.DrawString( "当前时间: " + ExtendValue1, GUIset.ExpFont, NameBrush, SX + Width + 10, hh );
		}
	}
	
	//组件绘制工作2
	//绘制组件的端口链接导线,需要在所有组件基础绘制完成之后进行
	//绘制端口的方框背景
	public override void Draw2( Graphics g )
	{
		if( PackHid ) {
			return;
		}
		if( isNewTick != 0 ) {
			return;
		}
		DrawInterfaceLine( g );
		
		//遍历接口列表
		for( int i = 0; n_ImagePanel.ImagePanel.Flash && i < this.LinkInterfaceList.Length; ++i ) {
			
			if( !n_ImagePanel.ImagePanel.Flash ) {
				break;
			}
			if( this.LinkInterfaceList[ i ][ 0 ] != "" ) {
				continue;
			}
			//绘制引擎接口预连接
			string LinkName = this.LinkInterfaceList[ i ][ 1 ].Split( '_' )[ 1 ];
			
			int PickNumber = 0;
			string Target = null;
			int tn = 0;
			MyFileObject ta = null;
			
			if( !this.myObjectList.isModuleLib ) {
				foreach( MyObject mo in myObjectList ) {
					if( !(mo is MyFileObject) ) {
						continue;
					}
					if( mo == this ) {
						continue;
					}
					MyFileObject mm = (MyFileObject)mo;
					
					//搜索组件提供的接口列表
					for( int j = 0; j < mm.InterfaceList.Length; ++j ) {
						if( LinkName == mm.InterfaceList[ j ][ 1 ].Split( '_' )[ 1 ] ) {
							
							PickNumber++;
							Target = mm.Name + "." + mm.InterfaceList[ j ][ 2 ];
							ta = mm;
							tn = j;
							
							//绘制接口之间的预连接
							IPort tp = mm.IPortList[ j ];
							
							Shape.DrawEngineLine( g, InterfacePreLinkPen,
							                        this.MidX + this.IPortList[ this.InterfaceList.Length + i ].MidX,
							                        this.MidY + this.IPortList[ this.InterfaceList.Length + i ].MidY,
							                        mm.MidX + tp.MidX,
							                        mm.MidY + tp.MidY );
							
							//Shape.DrawRectangleLine( g, InterfacePreLinkPen,
							//                        this.MidX + this.IPortList[ this.InterfaceList.Length + i ].MidX,
							//                        this.MidY + this.IPortList[ this.InterfaceList.Length + i ].MidY,
							//                        mm.MidX + mm.IPortList[ j ].MidX,
							//                        mm.MidY + mm.IPortList[ j ].MidY );
							
							
						}
					}
				}
			}
			if( PickNumber == 1 ) {
				LinkInterfaceList[ i ][ 0 ] = Target;
				IPortList[ InterfaceList.Length + i ].TargetIPort = ta.IPortList[tn];
			}
		}
		if( G.CGPanel.HideLine == 0 ) {
			//本应是第3级别绘制
			//绘制端口配置
			for( int i = 0; i < PORTList.Length; ++i ) {
				PORTList[ i ].Draw3( g );
			}
			//绘制总线配置
			for( int i = 0; i < ZWireList.Length; ++i ) {
				ZWireList[ i ].Draw3( g );
			}
		}
		//绘制接口
		if( !this.myObjectList.isModuleLib ) {
			
			//刷新
			for( int i = 0; i < IPortList.Length; ++i ) {
				IPortList[i].Refresh();
			}
			//绘制接口
			if( myObjectList.MouseOnObject == this ) {
				this.DrawInterface( g );
			}
			
		}
	}
	
	//绘制接口
	public void DrawInterfaceLine( Graphics g )
	{
		if( PackHid ) {
			return;
		}
		if( isNewTick != 0 ) {
			return;
		}
		float midx = this.MidX;
		float midy = this.MidY;
		if( !GroupVisible ) {
			n_GroupList.Group gr = G.CGPanel.mGroupList.FindGroup( GroupMes );
			
			if( gr != null ) {
				midx = gr.GetMidX();
				midy = gr.GetMidY();
			}
			else {
				//理论上不可能执行这里
				n_Debug.Warning.BUG( "<DrawInterfaceLine> 模块分组为空! " + GroupMes );
			}
		}
		
		//遍历接口列表
		for( int i = 0; i < IPortList.Length; ++i ) {
			if( !IPortList[i].isLink ) {
				continue;
			}
			//绘制已经连接的接口
			if( IPortList[i].TargetIPort != null ) {
				
				HardModule tar = (HardModule)IPortList[i].TargetIPort.Owner;
				if( !GroupVisible && tar.GroupMes == GroupMes ) {
					continue;
				}

				if( IPortList[i].GetMessage()[1] == "linkinterface_RFreceive" ) {
					float x1 = midx + (IPortList[i].TargetIPort.Owner.MidX - midx) / 3;
					float y1 = midy + (IPortList[i].TargetIPort.Owner.MidY - midy) / 3;
					float x2 = midx + (IPortList[i].TargetIPort.Owner.MidX - midx) * 2 / 3;
					float y2 = midy + (IPortList[i].TargetIPort.Owner.MidY - midy) * 2 / 3;
					g.DrawLine( GUIset.RF_Pen,x1, y1, x2, y2 );
				}
				else if( IPortList[i].GetMessage()[1] == "linkinterface_IRreceive" ) {
					float x1 = midx + (IPortList[i].TargetIPort.Owner.MidX - midx) / 3;
					float y1 = midy + (IPortList[i].TargetIPort.Owner.MidY - midy) / 3;
					float x2 = midx + (IPortList[i].TargetIPort.Owner.MidX - midx) * 2 / 3;
					float y2 = midy + (IPortList[i].TargetIPort.Owner.MidY - midy) * 2 / 3;
					g.DrawLine( GUIset.IR_Pen,x1, y1, x2, y2 );
				}
				else {
					float x1 = midx + (IPortList[i].TargetIPort.Owner.MidX - midx) * 33 / 100;
					float y1 = midy + (IPortList[i].TargetIPort.Owner.MidY - midy) * 33 / 100;
					float x2 = midx + (IPortList[i].TargetIPort.Owner.MidX - midx) * 66 / 100;
					float y2 = midy + (IPortList[i].TargetIPort.Owner.MidY - midy) * 66 / 100;
					g.DrawLine( GUIset.NOR_Pen,x1, y1, x2, y2 );
					//g.DrawString( IPortList[i].TargetIPort.GetMessage()[2], GUIset.ModuleNameFont, Brushes.SlateGray, x1 - 15, y1 - 20 );
					
					//或者矩形折线
					/*
					Shape.DrawRectangleLine( g, InterfaceLinkPen,
						StartX + this.MidX + IPortList[i].MidX,
						StartY + this.MidY + IPortList[i].MidY,
						StartX + IPortList[i].TargetIPort.Owner.MidX + IPortList[i].TargetIPort.MidX,
						StartY + IPortList[i].TargetIPort.Owner.MidY + IPortList[i].TargetIPort.MidY );
					*/
				}
			}
		}
	}
	
	//组件绘制工作3
	//绘制组件的端口和名称,需要在所有链接导线绘制完成之后进行
	public override void Draw3( Graphics g )
	{
		if( PackHid ) {
			return;
		}
		if( isNewTick != 0 ) {
			return;
		}
		if( G.CGPanel.HideLine == 0 ) {
			//绘制端口配置
			for( int i = 0; i < PORTList.Length; ++i ) {
				PORTList[ i ].Draw2( g, myObjectList);
			}
			//绘制端口配置
			for( int i = 0; i < ZWireList.Length; ++i ) {
				ZWireList[ i ].Draw2( g, myObjectList );
			}
		}
	}
	
	//组件绘制工作1
	//绘制组件的外形等,基础绘制工作
	public override void DrawSim( Graphics g )
	{
		if( PackHid ) {
			return;
		}
		if( isNewTick != 0 ) {
			return;
		}
		//摄像机按照中心位置进行旋转
		GraphicsState gs = g.Save();
		
		n_SG.SG.Rotate( MidX, MidY, Angle );
		if( SwapPort ) {
			n_SG.SG.Swap( MidX, MidY, -1, 1 );
		}
		
		//绘制仿真元素
		if( !this.myObjectList.isModuleLib && G.SimulateMode && SimList.Length > 0 && SimList[0] != null ) {
			
			if( SimList[0].SimType == 100 ) {
				
				//g.Restore( gs );
				
				for( int i = 0; i < SimList.Length; ++i ) {
					if( SimList[i] != null ) {
						//SimList[i].SetColor( DataList[3] );
						SimList[i].Draw( g, MidX, MidY );
					}
				}
				g.Restore( gs );
			}
			else {
				for( int i = 0; i < SimList.Length; ++i ) {
					if( SimList[i] != null ) {
						if( SimList[i].SimType != SimulateObj.LED || DataList[SimList[i].Value1] != 0 ) {
							if( SimList[i].SimType == SimulateObj.LED ) {
								SimList[i].SetColor( DataList[3+i] );
							}
							SimList[i].Draw( g, MidX, MidY );
						}
					}
				}
				g.Restore( gs );
			}
		}
		else {
			g.Restore( gs );
		}
	}
	
	//绘制导线轨迹索引图
	public void DrawLineIndex( Graphics g )
	{
		if( PackHid ) {
			return;
		}
		if( isNewTick != 0 ) {
			return;
		}
		//绘制端口配置
		for( int i = 0; i < PORTList.Length; ++i ) {
			PORTList[ i ].DrawLineIndex( g, myObjectList );
		}
	}
	
	//组件绘制工作4
	//绘制组件高亮选中
	public override void DrawHighLight( Graphics g )
	{
		if( PackHid ) {
			return;
		}
		if( isNewTick != 0 ) {
			return;
		}
		if( isMousePress ) {
			return;
		}
		int x = SX - 4;
		int y = SY - 4 - this.ExYHPadding;
		int w = Width - 1 + 8;
		int h = Height - 1 + 8 + this.ExYLPadding * 2;
		//g.DrawRectangle( GUIset.组件高亮边框_Pen2, x, y, w, h );
		//g.DrawRectangle( GUIset.组件高亮边框_Pen1, x, y, w, h );
		
		this.VPanel.Draw( g );
	}
	
	//=======================================================================================================
	
	public string GetBindKeyList()
	{
		string r = "";
		for( int i = 0; i < SimList.Length; ++i ) {
			if( SimList[i] != null  ) {
				
				if( SimList[i].SimType == SimulateObj.T_IO_INPUT || SimList[i].SimType == SimulateObj.T_ButtonCircle || SimList[i].SimType == SimulateObj.T_ButtonRec ) {
					
					r += ((int)SimList[i].BindKey).ToString() + ",";
					continue;
				}
			}
			r += ",";
		}
		return r.TrimEnd( ',' );
	}
	
	public void SetBindKeyList( string[] ss )
	{
		for( int i = 0; i < ss.Length; ++i ) {
			if( SimList[i] != null && ss[i] != "" ) {
				
				if( SimList[i].SimType == SimulateObj.T_IO_INPUT || SimList[i].SimType == SimulateObj.T_ButtonCircle || SimList[i].SimType == SimulateObj.T_ButtonRec ) {
					
					try {
					Keys kk = (Keys)(int.Parse( ss[i] ));
					if( kk != Keys.None ) {
						SimList[i].BindKey = kk;
						GUIcoder.UseBindKey = true;
					}
					} catch {
						n_Debug.Warning.BUG( "<SetBindKeyList> 绑定按键异常: - [" + ss[i] + "]" );
					}
				}
			}
		}
	}
	
	//=======================================================================================================
	
	public void MyKeyDown( Keys k )
	{
		for( int i = 0; i < SimList.Length; ++i ) {
			if( SimList[i] != null  ) {
				
				if( SimList[i].SimType == SimulateObj.T_IO_INPUT || SimList[i].SimType == SimulateObj.T_ButtonCircle || SimList[i].SimType == SimulateObj.T_ButtonRec ) {	
					SimList[i].MyKeyDown( k );
				}
			}
		}
	}
	
	public void MyKeyUp( Keys k )
	{
		for( int i = 0; i < SimList.Length; ++i ) {
			if( SimList[i] != null  ) {
				
				if( SimList[i].SimType == SimulateObj.T_IO_INPUT || SimList[i].SimType == SimulateObj.T_ButtonCircle || SimList[i].SimType == SimulateObj.T_ButtonRec ) {
					SimList[i].MyKeyUp( k );
				}
			}
		}
	}
	
	//=======================================================================================================
	
	bool PressPort;
	
	//鼠标按下事件, 在组件中返回 true,不在组件中返回 false.
	public override bool MouseDown1( int mX, int mY )
	{
		if( PackHid ) {
			return false;
		}
		//分发仿真事件
		bool on = false;
		bool Quit = false;
		SimMouseDown( out on, out Quit, mX - MidX, mY - MidY );
		
		if( on ) {
			IgnoreHighLight = true;
		}
		
		if( Quit ) {
			return true;
		}
		if( !MouseIsInside( mX, mY ) ) {
			if( isHighLight ) {
				isHighLight = false;
			}
			return on;
		}
		
		if( myObjectList.SelectPort != null && myObjectList.SelectPort.FuncName == PortFuncName.INTERFACE ) {
			if( myObjectList.SelectPort.Owner == this ) {
				n_Debug.Warning.WarningMessage = ( "不允许连接到自身: " + this.Name );
				return true;
			}
			myObjectList.SelectPort.TargetModule = this;
			myObjectList.SelectPort = null;
			return true;
		}
		//if( !G.SimulateMode ) {
		
		PressPort = false;
		
		if( G.CGPanel.HideLine == 0 ) {
		//处理单端口类列表
		for( int i = 0; i < PORTList.Length; ++i ) {
			
			//设置为鼠标按下状态
			if( PORTList[i].FuncName == PortFuncName.C_Analog || PORTList[i].FuncName == PortFuncName.C_Digital ) {
				G.CGPanel.myCLineList.SetMoveStatus( (int)(MidX + PORTList[i].X), (int)(MidY + PORTList[i].Y) );
			}
			
			if( !(
				  PackOwner == null ||
				  (PackOpenMPort && isControlModule) || //只有主控器才会判断MPort属性 (小熊派按钮等等不允许再重新连接)
			      this.ImageName == SPMoudleName.SYS_iport && PORTList[ i ].ClientType == PortClientType.MASTER ||
			      PORTList[ i ].FuncName == PortFuncName.UART
			     ) ) {
				continue;
			}
			
			if( PORTList[ i ].isMouseInPort( mX, mY  ) ) {
				IgnoreHighLight = true;
				PressPort = true;
				if( myObjectList.SelectPort == null ) {
					
					if( PORTList[i].FuncName == PortFuncName.C_Analog || PORTList[i].FuncName == PortFuncName.C_Digital ) {
						
						if( !G.CGPanel.myCLineList.ExistPress ) {
							G.CGPanel.myCLineList.AddList( true, mX, mY, mX, mY );
						}
						else {
							G.CGPanel.myCLineList.NotAddList = true;
						}
						continue;
					}
					
					//如果当前端口没有连接目标, 那么设置为选中端口; 否则删除目标
					if( PORTList[ i ].TargetPort != null ) {
						
						//不允许点击从端口删除导线了
						
						/*
						if( PORTList[ i ].MidPortIndex != -1 ) {
							myObjectList.GPanel.myMidPortList.Delete( PORTList[ i ].MidPortIndex );
							PORTList[ i ].MidPortIndex = -1;
						}
						PORTList[ i ].TargetPort = null;
						
						//这里需要更新端口名称
						G.CGPanel.RefreshLinePortName();
						*/
						
						myObjectList.SelectPort = PORTList[ i ];
					}
					else {
						myObjectList.SelectPort = PORTList[ i ];
					}
					
					
					//考虑到PULL类型端口需要处理主从, 所以不删除目标
					//myObjectList.SelectPort = PORTList[ i ];
					
					
					break;
				}
				int ci = myObjectList.SelectPort.ColorIndex;
				Port Client = myObjectList.SelectPort;
				Port Master = PORTList[ i ];
				if( Client.ClientType == PortClientType.MASTER && Master.ClientType == PortClientType.CLIENT ) {
					Port t = Client;
					Client = Master;
					Master = t;
				}
				if( Client.ClientType == PortClientType.CLIENT &&
				    Master.ClientType == PortClientType.CLIENT &&
					Client.FuncName == PortFuncName.LINE ) {
					Port t = Client;
					Client = Master;
					Master = t;
				}
				
				if( Client.isBus != Master.isBus ) {
					n_Debug.Warning.WarningMessage = ( "主从针脚的总线类型必须相同:\n" + 
					               Client.isBus + " " + Master.isBus);
					break;
				}
				//如果不检查此项内容, 面包板同名端口连接会导致死机
				if( Client.Owner == Master.Owner && Client.Name == Master.Name ) {
					n_Debug.Warning.WarningMessage = ( "面包板类模块自身的同名针脚不允许相连:\n" + Client.Name );
					break;
				}
				
				/*
				//判断主板端口是否被复用
				for( int ii = 0; ii < myObjectList.ModuleList.Length; ++ii ) {
					if( myObjectList.ModuleList[ ii ] == null ) {
						continue;
					}
					if( myObjectList.ModuleList[ ii ].ChipIndex != ChipIndex ) {
						continue;
					}
					if( myObjectList.ModuleList[ ii ] is HardModule ) {
						HardModule hm = (HardModule)myObjectList.ModuleList[ ii ];
						if( hm.isControlModule ) {
							
						}
					}
				}
				*/
				
				/*
				if( Client.Owner == Master.Owner ) {
					G.FlashBox.Run( "不能链接到自身模块:\n" + 
					               Client.Owner.Name + " " + Client.Name + "\n" +
					               Master.Owner.Name + " " + Master.Name);
					break;
				}
				*/
				
				if( Master.FuncName == PortFuncName.PULL ) {
					Port t = Client;
					Client = Master;
					Master = t;
				}
				if( Client.FuncName == PortFuncName.PULL ) {
					Client.TargetPort = Master;
				}
				else if( Client.FuncName == PortFuncName.LINE ) {
					if( Master.ClientType == PortClientType.MASTER ) {
						Client.TargetPort = Master;
					}
					else {
						Master.TargetPort = Client;
						Client.TargetPort = null;
					}
				}
				else if( Master.FuncName == PortFuncName.LINE ) {
					if( Client.ClientType == PortClientType.MASTER ) {
						Master.TargetPort = Client;
					}
					else {
						Client.TargetPort = Master;
						Master.TargetPort = null;
					}
				}
				else {
					if( Client.ClientType != PortClientType.CLIENT || Master.ClientType != PortClientType.MASTER ) {
						
						if( Master.FuncName != PortFuncName.GND && Client.FuncName != PortFuncName.GND &&
						    Master.FuncName != PortFuncName.VCC && Client.FuncName != PortFuncName.VCC &&
						    
						    Master.FuncName != PortFuncName.VCC6t9V && Client.FuncName != PortFuncName.VCC6t9V &&
						    Master.FuncName != PortFuncName.VCC3_3V && Client.FuncName != PortFuncName.VCC3_3V ) {
							n_Debug.Warning.WarningMessage = ( "只能链接主从针脚:\n" +
						               Client.Owner.Name + " " + Client.Name + "\n" +
						               Master.Owner.Name + " " + Master.Name );
							break;
						}
					}
					//判断是否为串口, 允许忽略串口序号的不同
					bool isRx = Client.FuncName == PortFuncName.RxD;
					isRx &= Master.FuncName.IndexOf( PortFuncName.RxDn ) != -1;
					bool isTx = Client.FuncName == PortFuncName.TxD;
					isTx &= Master.FuncName.IndexOf( PortFuncName.TxDn ) != -1;
					
					//判断是否是3.3V模式
					bool isVCC3_3 = GUIcoder.isVCC3_3 && (Master.FuncName == PortFuncName.VCC3_3V) && (Client.FuncName == PortFuncName.VCCA);
					bool isVCC5 = !GUIcoder.isVCC3_3 && (Master.FuncName == PortFuncName.VCC) && (Client.FuncName == PortFuncName.VCCA);
					
					//忽略VEX模式INT类型的需求
					bool ignVexINT = false;
					if( GUIcoder.cputype1 == "VM" &&
					    (Client.FuncName == PortFuncName.INT) &&
					    ((Master.FuncName + ",").IndexOf( PortFuncName.IN ) != -1) ) {
						ignVexINT = true;
					}
					if( !ignVexINT && !(isRx || isTx ) && !isVCC3_3 && !isVCC5 &&
					    (Master.FuncName + ",").IndexOf( Client.FuncName ) == -1 &&
					    (Master.FuncName != PortFuncName.VCC || Client.FuncName != PortFuncName.VCC6t9V) ) {
					    //!( (Master.FuncName == ",VCC,"|| Master.FuncName == ",GND,") && Client.FuncName == ",OUT," ) ) {
						n_Debug.Warning.WarningMessage = ( "针脚类型不同,无法连接:\n" +
						               Client.FuncName + " -> " + Master.FuncName );
						break;
					}
					//提示不建议连接的针脚
					if( Master.isNotUsePort() ) {
						MessageBox.Show( "注意: 主板左上角的一排白色针脚(8个)尽量不要使用! 建议换成其他针脚.\n(详情参考主板的模块信息说明)" );
					}
					Client.TargetPort = Master;
				}
				
				//如果从主端口开始连接, 需要交换过渡节点索引
				if( myObjectList.SelectPort.MidPortIndex != -1 && myObjectList.SelectPort.ClientType == PortClientType.MASTER ) {
					Client.MidPortIndex = myObjectList.SelectPort.MidPortIndex;
					myObjectList.GPanel.myMidPortList.Swap( Client.MidPortIndex );
					myObjectList.SelectPort.MidPortIndex = -1;
				}
				
				//这里是处理 pull 和 line 连接导致的混乱
				//如果从主端口开始连接, 需要交换过渡节点索引
				if( Master.MidPortIndex != -1 ) {
					Client.MidPortIndex = Master.MidPortIndex;
					myObjectList.GPanel.myMidPortList.Swap( Client.MidPortIndex );
					Master.MidPortIndex = -1;
				}
				Client.ColorIndex = ci;
				
				myObjectList.SelectPort = null;
				G.CGPanel.RefreshLinePortName();
				break;
			}
		}
		//处理总线端口类列表
		for( int i = 0; i < ZWireList.Length; ++i ) {
			if( ZWireList[ i ].isMouseInPort( mX, mY  ) ) {
				PressPort = true;
				if( myObjectList.SelectPort == null ) {
					myObjectList.SelectPort = ZWireList[ i ];
					if( myObjectList.SelectPort.TargetPort != null ) {
						//myObjectList.SelectPort.TargetPort = null;
					}
					break;
				}
				Port Client = myObjectList.SelectPort;
				Port Master = ZWireList[ i ];
				if( Client.ClientType == PortClientType.MASTER && Master.ClientType == PortClientType.CLIENT ) {
					Port t = Client;
					Client = Master;
					Master = t;
				}
				if( Client.isBus != Master.isBus ) {
					n_Debug.Warning.WarningMessage = ( "主从针脚的总线类型必须相同:\n" + 
					               Client.isBus + " " + Master.isBus);
					break;
				}
				if( Client.Owner == Master.Owner ) {
					n_Debug.Warning.WarningMessage = ( "不能链接到自身模块的针脚:\n" + 
					               Client.Owner.Name + " " + Client.Name + "\n" +
					               Master.Owner.Name + " " + Master.Name);
					break;
				}
				if( Client.ClientType != PortClientType.CLIENT || Master.ClientType != PortClientType.MASTER ) {
					n_Debug.Warning.WarningMessage = ( "只能链接主从针脚:\n" +
					               Client.Owner.Name + " " + Client.Name + "\n" +
					               Master.Owner.Name + " " + Master.Name );
					break;
				}
				if( (Master.FuncName + ",").IndexOf( Client.FuncName ) == -1 ) {
					n_Debug.Warning.WarningMessage = ( "针脚类型不同,无法连接:\n" +
					               Client.FuncName + " -> " + Master.FuncName ); 
					break;
				}
				if( Master.SubPortConfig != null && Client.SubPortConfig != null ) {
					if( Master.SubPortConfig.Length != Client.SubPortConfig.Length ) {
						n_Debug.Warning.WarningMessage = ( "针脚数目配置不匹配,无法连接:\n" +
					              Client.FuncName + " -> " + Master.FuncName );
						break;
					}
					for( int n = 0; n < Master.SubPortConfig.Length; n++ ) {
						if( Client.SubPortConfig[n] == '1' && Master.SubPortConfig[n] == '0' ) {
							n_Debug.Warning.WarningMessage = ( "针脚数目配置不匹配,无法连接:\n" +
					               Client.FuncName + " -> " + Master.FuncName );
							goto end;
						}
					}
				}
				Client.TargetPort = Master;
				myObjectList.SelectPort = null;
				end:;
				break;
			}
		}
		}
		
		//接口鼠标点击事件
		PressPort |= IPortListMouseDown( mX, mY );
		//}
		
		if( this.myObjectList.MouseOnObject == this && isMouseOnBase ) {
			isMousePress = true;
			Last_mX = mX;
			Last_mY = mY;
			
			Start_mX = this.SX;
			Start_mY = this.SY;
		}
		return true;
	}
	
	public void SimMouseDown( out bool on, out bool Quit, int mX, int mY )
	{
		on = false;
		Quit = false;
		
		if( G.SimulateMode ) {
			int ox = 0;
			int oy = 0;
			GetRealPoint( mX, mY, ref ox, ref oy );
			for( int i = 0; i < SimList.Length; ++i ) {
				if( SimList[i] != null  ) {
					int tx = ox;
					int ty = oy;
					if( SimList[i].SimType == SimulateObj.T_ValueSensor ) {
						//tx = mX;
						//ty = mY;
					}
					if( SimList[i].UserMouseDown( tx, ty ) ) {
						on = true;
						if( SimList[i].SimType == SimulateObj.T_IO_INPUT ||
						    SimList[i].SimType == SimulateObj.T_ButtonCircle ||
						    SimList[i].SimType == SimulateObj.T_ButtonRec ||
							SimList[i].SimType == SimulateObj.T_AD_XY ) {
							Quit = true;
						}
					}
				}
			}
		}
	}
	
	//鼠标松开事件
	public override void MouseUp1( int mX, int mY )
	{
		if( PackHid ) {
			return;
		}
		
		//分发仿真事件
		SimMouseUp();
		
		if( isNewTick == 0 ) {
			isMousePress = false;
			ignoreHit = false;
		}
	}
	
	public void SimMouseUp()
	{
		if( G.SimulateMode ) {
			for( int i = 0; i < SimList.Length; ++i ) {
				if( SimList[i] != null  ) {
					SimList[i].UserMouseUp();
				}
			}
		}
	}
	
	//鼠标移动事件,当鼠标在组件上时返回1,组件被拖动时返回2
	public override int MouseMove1( int mX, int mY )
	{
		if( PackHid ) {
			return 0;
		}
		if( isNewTick == MaxNewTick ) {
			isNewTick--;
			isMousePress = true;
			this.SX = mX - this.SX;
			this.SY = mY - this.SY;
			this.RefreshPanelLocation();
			Last_mX = mX;
			Last_mY = mY;
			
			Start_mX = this.SX;
			Start_mY = this.SY;
			return 2;
		}
		if( isNewTick > 0 ) {
			isNewTick--;
		}
		//分发仿真事件
		SimMouseMove( mX - MidX, mY - MidY );
		
		bool isMouseIn = MouseIsInside( mX, mY );
		if( !isMouseIn && !isMousePress ) {
			return 0;
		}
		
		//鼠标在模块上时不需要显示导线删除提示
		G.CGPanel.TakeMoIndex = -1;
		G.CGPanel.TakePoIndex = -1;
		
		if( G.CGPanel.HideLine == 0 ) {
		for( int i = 0; i < PORTList.Length; ++i ) {
			if( PORTList[ i ].isMouseInPort( mX, mY  ) ) {
				myObjectList.MouseOnPort = PORTList[ i ];
			}
		}
		for( int i = 0; i < ZWireList.Length; ++i ) {
			if( ZWireList[ i ].isMouseInPort( mX, mY  ) ) {
				myObjectList.MouseOnPort = ZWireList[ i ];
			}
		}
		}
		//接口鼠标悬停事件
		for( int i = 0; i < IPortList.Length; ++i ) {
			if( IPortList[ i ].isMouseInPort( mX, mY  ) ) {
				myObjectList.MouseOnIPort = IPortList[ i ];
			}
		}
		if( !isMousePress ) {
			return 1;
		}
		if( PressPort ) {
			return 1;
		}
		if( G.CGPanel.myModuleList.ShowPanelTime >= MyObjectList.ShowPanelMaxTime - 2 ) {
			
			int offx = SX;
			int offy = SY;
			SX = Start_mX + (mX - Last_mX);
			SY = Start_mY + (mY - Last_mY);
			
			if( isCircuit || Port.C_Rol == 0 ) {
				bool b = ADjToCross();
				if( b ) {
					myObjectList.ShowPanelTime = 100;
				}
			}
			
			PackModuleMove( SX - offx, SY - offy );
			
			//Last_mX = mX;
			//Last_mY = mY;
		}
		
		//同步拖动电路线列表
		G.CGPanel.myCLineList.AutoMove( SX - Start_mX, SY - Start_mY );
		
		this.RefreshPanelLocation();
		return 2;
	}
	
	//封包组件同步拖动
	public void PackModuleMove( int mX, int mY )
	{
		//判断是否封包带动相关模块拖动
		if( PackOwner != null ) {
			foreach( n_MyObject.MyObject mo in myObjectList ) {
				if(mo == this ) {
					continue;
				}
				if( !(mo is HardModule) ) {
					continue;
				}
				HardModule mm = (HardModule)mo;
				if( mm.PackOwner != null ) {
					mm.SX += mX;
					mm.SY += mY;
					mm.isMoved = true;
					mm.RefreshPanelLocation();
				}
			}
		}
	}
	
	public void SimMouseMove( int mX, int mY )
	{
		if( G.SimulateMode ) {
			int ox = 0;
			int oy = 0;
			GetRealPoint( mX, mY, ref ox, ref oy );
			for( int i = 0; i < SimList.Length; ++i ) {
				if( SimList[i] != null  ) {
					int tx = ox;
					int ty = oy;
					if( SimList[i].SimType == SimulateObj.T_ValueSensor ) {
						//tx = mX;
						//ty = mY;
					}
					SimList[i].UserMouseMove( tx, ty );
				}
			}
		}
	}
	
	public bool ADjToCross()
	{
		//SX = (int)(SX ) / 10 * 10;
		//SY = (int)(SY) / 10 * 10;
		
		int lasx = SX;
		int lasy = SY;
		
		SX = n_Common.Common.GetCrossValue( SX );
		SY = n_Common.Common.GetCrossValue( SY );
		
		return SX != lasx || SY != lasy;
	}
	
	//=======================================================================================================
	
	//获取实际的坐标
	public bool s_t_Angle;
	public float s_Angle;
	void GetRealPoint( int x, int y, ref int ox, ref int oy )
	{
		int offx = x;
		int offy = y;
		
		if( s_t_Angle ) {
			float a = 0;
			float r = n_RA.RA.GetR( out a, offx, offy );
			a += s_Angle;
			float tx = 0;
			float ty = 0;
			n_RA.RA.GetXY( out tx, out ty, a, r );
			ox = (int)tx;
			oy = (int)ty;
		}
		else {
			switch( Angle ) {
				case 0:		ox = offx; oy = offy; break;
				case 90:	ox = offy; oy = - offx; break;
				case 180:	ox = - offx; oy = - offy; break;
				case 270:	ox = - offy; oy = offx; break;
			}
			if( SwapPort ) {
				ox = -ox;
			}
		}
		
	}
	
	//设置用户参数
	public void SetUserValue( string vName, string vGroupMes, string vLanguage, int vX, int vY, int vAngle, bool swap )
	{
		Name = vName;
		GroupMes = vGroupMes;
		Language = vLanguage;
		SetAngle( vAngle );
		SX = vX;
		SY = vY;
		
		Lastmidx = MidX;
		Lastmidy = MidY;
		
		if( swap ) {
			Swap();
		}
		
		VPanel = new MyFileObjectPanel( this );
		
		this.RefreshPanelLocation();
	}
	
	//设置角度
	void SetAngle( int a )
	{
		Angle = 0;
		switch( a ) {
			case 0:		break;
			case 90:	Rol( 1 ); break;
			case 180:	Rol( 1 ); Rol( 1 ); break;
			case 270:	Rol( -1 ); break;
			default:	break;
		}
		//注意这里! 本来在 Rol 中已经设置了, 但是因为角度==0时, 不执行Rol,导致放缩时, 0度的模块不是按照中心放缩, 所以需要加上这个
		SX = Lastmidx - Width/2;
		SY = Lastmidy - Height/2;
	}
	
	
	//更新一个可变类型端口的实际类型
	public void RefreshPrePortName( Port p, string FuncName )
	{
		//把提取属性扩散到当前模块的其他同名端口上, 根据是否有链接对象设置为 MASTER 或 CLIENT
		HardModule hm = p.Owner;
		for( int i = 0; i < hm.PORTList.Length; ++i ) {
			Port cp = hm.PORTList[i];
			if( cp.CanChange && cp.Name == p.Name ) {
				if( cp.TargetPort != null ) {
					cp.ClientType = PortClientType.CLIENT;
				}
				else {
					cp.ClientType = PortClientType.MASTER;
				}
				cp.FuncName = FuncName;
				if( cp.PrePort != null ) {
					RefreshPrePortName( cp.PrePort, FuncName );
				}
			}
		}
	}
	
	//更新可变主端口的类型名称
	void RefreshTargetPortName( Port p, Port clientp )
	{
		string FuncName = clientp.FuncName;
		
		//把提取属性扩散到当前模块的其他同名端口上, 根据是否有链接对象设置为 MASTER 或 CLIENT
		HardModule hm = p.Owner;
		for( int i = 0; i < hm.PORTList.Length; ++i ) {
			Port cp = hm.PORTList[i];
			if( cp.CanChange && cp.Name == p.Name && cp.FuncName == PortFuncName.LINE ) {
				if( cp == p ) {
					cp.ClientType = PortClientType.MASTER;
				}
				else {
					cp.ClientType = PortClientType.CLIENT;
				}
				cp.FuncName = FuncName;
			}
		}
	}
	
	//反向更新可变从端口的类型名称
	void RefreshTargetPortName1( Port p )
	{
		//把提取属性扩散到当前模块的其他同名端口上, 根据是否有链接对象设置为 MASTER 或 CLIENT
		HardModule hm = p.Owner;
		Port master = null;
		for( int i = 0; i < hm.PORTList.Length; ++i ) {
			Port cp = hm.PORTList[i];
			if( cp.CanChange && cp.Name == p.Name ) {
				cp.ClientType = PortClientType.CLIENT;
				cp.FuncName = PortFuncName.LINE;
				if( cp.TargetPort != null ) {
					master = cp.TargetPort;
				}
			}
		}
		if( master != null ) {
			RefreshPrePortName( p, master.FuncName );
		}
	}
	
	//清空一个可变类型端口的实际类型
	void ClearPortName( Port p )
	{
		//把提取属性扩散到当前模块的其他同名端口上, 根据是否有链接对象设置为 MASTER 或 CLIENT
		HardModule hm = p.Owner;
		for( int i = 0; i < hm.PORTList.Length; ++i ) {
			Port cp = hm.PORTList[i];
			if( cp.CanChange && cp.Name == p.Name ) {
				cp.ClientType = PortClientType.CLIENT;
				cp.FuncName = PortFuncName.LINE;
				if( cp.PrePort != null ) {
					ClearPortName( cp.PrePort );
				}
			}
		}
	}
	
	//根据端口名称获取对应的端口对象
	public Port GetPort( string Name )
	{
		Port p = GetPortInner( Name );
		if( p != null ) {
			return p;
		}
		Name = n_HModCommon.HModCommon.GetName( ConfigList, Name );
		if( Name == null ) {
			return null;
		}
		p = GetPortInner( Name );
		if( p == null ) {
			//MessageBox.Show( "<Module.GetPort> 未定义的端口名称: " + this.Name + "." + Name );
		}
		return p;
	}
	
	//根据端口名称获取对应的端口对象
	public Port GetPortInner( string Name )
	{
		if( Name.StartsWith( "#" ) ) {
			int Index = int.Parse( Name.Remove( 0, 1 ) );
			return PORTList[ Index ];
		}
		for( int i = 0; i < PORTList.Length; ++i ) {
			if( PORTList[ i ].Name == Name ) {
				return PORTList[ i ];
			}
		}
		for( int i = 0; i < ZWireList.Length; ++i ) {
			if( ZWireList[ i ].Name == Name ) {
				return ZWireList[ i ];
			}
		}
		return null;
	}
	
	//把组件旋转90度,当 way 等于-1时向左旋转,为1时向右旋转
	public void Rol( int way )
	{
		Lastmidx = MidX;
		Lastmidy = MidY;
		
		if( way == 1 ) {
			if( Angle == 270 ) {
				Angle = 0;
			}
			else {
				Angle += 90;
			}
		}
		else {
			if( Angle == 0 ) {
				Angle = 270;
			}
			else {
				Angle -= 90;
			}
		}
		switch( Angle ) {
			case 0:		Width = (int)(SourceWidth * Scale); Height = (int)(SourceHeight * Scale); break;
			case 90:	Width = (int)(SourceHeight * Scale); Height = (int)(SourceWidth * Scale); break;
			case 180:	Width = (int)(SourceWidth * Scale); Height = (int)(SourceHeight * Scale); break;
			case 270:	Width = (int)(SourceHeight * Scale); Height = (int)(SourceWidth * Scale); break;
			default: break;
		}
		for( int i = 0; i < PORTList.Length; ++i ) {
			float txy = PORTList[ i ].X;
			PORTList[ i ].X = -way * PORTList[ i ].Y;
			PORTList[ i ].Y = way * txy;
			if( way == 1 ) {
				switch( PORTList[ i ].DirType ) {
					case E_DirType.UP: PORTList[ i ].DirType = E_DirType.RIGHT; break;
					case E_DirType.RIGHT: PORTList[ i ].DirType = E_DirType.DOWN; break;
					case E_DirType.DOWN: PORTList[ i ].DirType = E_DirType.LEFT; break;
					case E_DirType.LEFT: PORTList[ i ].DirType = E_DirType.UP; break;
					default:	break;
				}
			}
			else {
				switch( PORTList[ i ].DirType ) {
					case E_DirType.UP: PORTList[ i ].DirType = E_DirType.LEFT; break;
					case E_DirType.RIGHT: PORTList[ i ].DirType = E_DirType.UP; break;
					case E_DirType.DOWN: PORTList[ i ].DirType = E_DirType.RIGHT; break;
					case E_DirType.LEFT: PORTList[ i ].DirType = E_DirType.DOWN; break;
					default:	break;
				}
			}
		}
		for( int i = 0; i < ZWireList.Length; ++i ) {
			float txy = ZWireList[ i ].X;
			ZWireList[ i ].X = -way * ZWireList[ i ].Y;
			ZWireList[ i ].Y = way * txy;
			if( way == 1 ) {
				switch( ZWireList[ i ].DirType ) {
					case E_DirType.UP: ZWireList[ i ].DirType = E_DirType.RIGHT; break;
					case E_DirType.RIGHT: ZWireList[ i ].DirType = E_DirType.DOWN; break;
					case E_DirType.DOWN: ZWireList[ i ].DirType = E_DirType.LEFT; break;
					case E_DirType.LEFT: ZWireList[ i ].DirType = E_DirType.UP; break;
					default:	break;
				}
			}
			else {
				switch( ZWireList[ i ].DirType ) {
					case E_DirType.UP: ZWireList[ i ].DirType = E_DirType.LEFT; break;
					case E_DirType.RIGHT: ZWireList[ i ].DirType = E_DirType.UP; break;
					case E_DirType.DOWN: ZWireList[ i ].DirType = E_DirType.RIGHT; break;
					case E_DirType.LEFT: ZWireList[ i ].DirType = E_DirType.DOWN; break;
					default:	break;
				}
			}
		}
		SX = Lastmidx - Width/2;
		SY = Lastmidy - Height/2;
		
		RefreshIPortList();
	}
}
}



